package com.spring.interceptor;

import com.jntoo.db.DB;
import com.jntoo.db.utils.Convert;
import com.jntoo.db.utils.StringUtil;
import com.spring.util.JwtTokenUtils;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Map;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

@Component
public class TokenInterceptor implements HandlerInterceptor {

    @Resource
    private JwtTokenUtils jwtTokenUtils;

    /**
     * 在请求处理之前进行调用（Controller方法调用之前）
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        String token = request.getHeader("token");

        // 在这里设置跨域请求处理
        // 检查请求头中的Origin是否存在，并且响应头中的Access-Control-Allow-Origin是否为空
        if (!StringUtil.isNullOrEmpty(request.getHeader("Origin")) && response.getHeader("Access-Control-Allow-Origin") == null) {
            // 将请求头中的Origin添加到响应头中，允许跨域请求
            response.addHeader("Access-Control-Allow-Origin", request.getHeader("Origin"));
            // 设置允许的请求方法
            response.addHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE");
            // 设置允许的请求头
            response.addHeader("Access-Control-Allow-Headers", "x-requested-with, token, content-type, auth-token, app-http, Authorization");
            // 允许发送包含凭据的请求（如Cookie）
            response.addHeader("Access-Control-Allow-Credentials", "true");
            // 设置预检请求的缓存时间（单位：秒）
            response.addHeader("Access-Control-Max-Age", Integer.toString(86400 * 7));
            // 检查请求方法是否为OPTIONS,预检请求
            if ("OPTIONS".equals(request.getMethod().toUpperCase())) {
                PrintWriter writer = null;
                try {
                    // 获取响应的输出流
                    writer = response.getWriter();
                    // 输出"ok"作为响应内容
                    writer.println("ok");
                    // 刷新输出流
                    writer.flush();
                    // 关闭输出流
                    writer.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                // 返回false，表示拦截器执行到此处后直接返回，不继续执行后续操
                // 表示浏览器正在发送预检请求，而不是实际的业务请求。为了满足跨域请求的要求，拦截器直接返回响应，告诉浏览器允许该跨域请求，并在响应中添加了相应的跨域配置信息。
                //如果预检请求不通过，浏览器将不会继续发送实际的业务请求，从而防止了潜在的安全问题和数据泄露。
                return false;
            }
        }

        try {
            // 从token中获取声明并进行处理
            jwtTokenUtils.getClaimFromToken(
                    token,
                    map -> {
                        // 获取当前请求的HttpSession对象
                        HttpSession session = request.getSession();
                        // 设置会话的最大非活动时间为300秒（即5分钟）
                        session.setMaxInactiveInterval(300);

                        // 检查必要的信息是否存在
                        if (
                                StringUtil.isNullOrEmpty(map.get("tab")) ||
                                        StringUtil.isNullOrEmpty(map.get("id")) ||
                                        StringUtil.isNullOrEmpty(map.get("cx")) ||
                                        StringUtil.isNullOrEmpty(map.get("username")) ||
                                        StringUtil.isNullOrEmpty(map.get("login"))
                        ) {
                            // 如果任何一个信息缺失，则使会话无效
                            session.invalidate();
                            return null;
                        }

                        // 从数据库中检索相关数据
                        String table = Convert.toStr(map.get("tab"));
                        String id = Convert.toStr(map.get("id"));
                        Map<String, Object> data = DB.name(table).find(id);

                        // 如果查询结果为空，则使会话无效
                        if (data == null || data.isEmpty()) {
                            session.invalidate();
                            return null;
                        }

                        // 将必要的值设置为会话的属性
                        session.setAttribute("cx", map.get("cx"));
                        session.setAttribute("login", map.get("login"));
                        session.setAttribute("username", map.get("username"));

                        // 将查询结果中的键值对也设置为会话的属性
                        for (Map.Entry<String, Object> entry : data.entrySet()) {
                            session.setAttribute(entry.getKey(), entry.getValue());
                        }

                        return null;
                    }
            );
        } catch (Exception e) {}
        return true;
        //如果设置为false时，被请求时，拦截器执行到此处将不会继续操作
        //如果设置为true时，请求将会继续执行后面的操作
    }

    /**
     * 请求处理之后进行调用，但是在视图被渲染之前（Controller方法调用之后）
     */
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) {
        //         System.out.println("执行了TestInterceptor的postHandle方法");
    }

    /**
     * 在整个请求结束之后被调用，也就是在DispatcherServlet 渲染了对应的视图之后执行（主要是用于进行资源清理工作）
     */
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
        //        System.out.println("执行了TestInterceptor的afterCompletion方法");
    }
}
